home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 4 / Example 4.8 / app.cpp next >
Encoding:
C/C++ Source or Header  |  2006-08-01  |  7.3 KB  |  278 lines

  1. //////////////////////////////////////////////////////////////
  2. // Example 4.8: Texture Splatting with Pixelshader            //
  3. // Written by: C. Granberg, 2005                            //
  4. //////////////////////////////////////////////////////////////
  5.  
  6. #include <windows.h>
  7. #include <d3dx9.h>
  8. #include <vector>
  9. #include "debug.h"
  10. #include "heightMap.h"
  11. #include "terrain.h"
  12.  
  13. #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
  14. #define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
  15.  
  16. class APPLICATION
  17. {
  18.     public:
  19.         APPLICATION();
  20.         HRESULT Init(HINSTANCE hInstance, int width, int height, bool windowed);
  21.         HRESULT Update(float deltaTime);
  22.         HRESULT Render();
  23.         HRESULT Cleanup();
  24.         HRESULT Quit();
  25.  
  26.     private:
  27.         IDirect3DDevice9* m_pDevice; 
  28.         TERRAIN m_terrain;
  29.  
  30.         float m_angle, m_radius;
  31.         bool m_wireframe;
  32.         DWORD m_time;
  33.         int m_fps, m_lastFps;
  34.         HWND m_mainWindow;
  35.         ID3DXFont *m_pFont;
  36. };
  37.  
  38. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
  39. {
  40.     APPLICATION app;
  41.  
  42.     if(FAILED(app.Init(hInstance, 800, 600, true)))
  43.         return 0;
  44.  
  45.     MSG msg;
  46.     memset(&msg, 0, sizeof(MSG));
  47.     int startTime = timeGetTime(); 
  48.  
  49.     while(msg.message != WM_QUIT)
  50.     {
  51.         if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  52.         {
  53.             ::TranslateMessage(&msg);
  54.             ::DispatchMessage(&msg);
  55.         }
  56.         else
  57.         {    
  58.             int t = timeGetTime();
  59.             float deltaTime = (t - startTime)*0.001f;
  60.  
  61.             app.Update(deltaTime);
  62.             app.Render();
  63.  
  64.             startTime = t;
  65.         }
  66.     }
  67.  
  68.     app.Cleanup();
  69.  
  70.     return msg.wParam;
  71. }
  72.  
  73. APPLICATION::APPLICATION()
  74. {
  75.     m_pDevice = NULL; 
  76.     m_mainWindow = 0;
  77.     m_angle = 0.0f;
  78.     m_radius = 100.0f;
  79.     m_wireframe = false;
  80.     m_fps = m_lastFps = 0;
  81.     m_time = GetTickCount();
  82.  
  83.     srand(GetTickCount());
  84. }
  85.  
  86. HRESULT APPLICATION::Init(HINSTANCE hInstance, int width, int height, bool windowed)
  87. {
  88.     debug.Print("Application initiated");
  89.  
  90.     //Create Window Class
  91.     WNDCLASS wc;
  92.     memset(&wc, 0, sizeof(WNDCLASS));
  93.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  94.     wc.lpfnWndProc   = (WNDPROC)::DefWindowProc; 
  95.     wc.hInstance     = hInstance;
  96.     wc.lpszClassName = "D3DWND";
  97.  
  98.     //Register Class and Create new Window
  99.     RegisterClass(&wc);
  100.     m_mainWindow = CreateWindow("D3DWND", "Example 4.8: Texture Splatting with Pixelshader", WS_EX_TOPMOST, 0, 0, width, height, 0, 0, hInstance, 0); 
  101.     SetCursor(NULL);
  102.     ShowWindow(m_mainWindow, SW_SHOW);
  103.     UpdateWindow(m_mainWindow);
  104.  
  105.     //Create IDirect3D9 Interface
  106.     IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
  107.  
  108.     if(d3d9 == NULL)
  109.     {
  110.         debug.Print("Direct3DCreate9() - FAILED");
  111.         return E_FAIL;
  112.     }
  113.  
  114.     //Check that the Device supports what we need from it
  115.     D3DCAPS9 caps;
  116.     d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
  117.  
  118.     //Hardware Vertex Processing or not?
  119.     int vp = 0;
  120.     if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  121.         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  122.     else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  123.  
  124.     //Check vertex & pixelshader versions
  125.     if(caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
  126.     {
  127.         debug.Print("Warning - Your graphic card does not support vertex and pixelshaders version 2.0");
  128.     }
  129.  
  130.     //Set D3DPRESENT_PARAMETERS
  131.     D3DPRESENT_PARAMETERS d3dpp;
  132.     d3dpp.BackBufferWidth            = width;
  133.     d3dpp.BackBufferHeight           = height;
  134.     d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
  135.     d3dpp.BackBufferCount            = 1;
  136.     d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
  137.     d3dpp.MultiSampleQuality         = 0;
  138.     d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
  139.     d3dpp.hDeviceWindow              = m_mainWindow;
  140.     d3dpp.Windowed                   = windowed;
  141.     d3dpp.EnableAutoDepthStencil     = true; 
  142.     d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
  143.     d3dpp.Flags                      = 0;
  144.     d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  145.     d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
  146.  
  147.     //Create the IDirect3DDevice9
  148.     if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow,
  149.                                  vp, &d3dpp, &m_pDevice)))
  150.     {
  151.         debug.Print("Failed to create IDirect3DDevice9");
  152.         return E_FAIL;
  153.     }
  154.  
  155.     //Release IDirect3D9 interface
  156.     d3d9->Release();
  157.  
  158.     D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,  
  159.                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  160.                    DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);
  161.  
  162.     //Create Terrain
  163.     m_terrain.Init(m_pDevice, INTPOINT(100,100));
  164.  
  165.     //Set sampler state
  166.     m_pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  167.     m_pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  168.     m_pDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
  169.  
  170.     return S_OK;
  171. }
  172.  
  173. HRESULT APPLICATION::Update(float deltaTime)
  174. {
  175.     //Control camera
  176.     m_angle += deltaTime * 0.5f;
  177.     D3DXMATRIX  matWorld, matView, matProj;        
  178.     D3DXVECTOR2 centre = D3DXVECTOR2(50, 50);
  179.     D3DXVECTOR3 Eye    = D3DXVECTOR3(centre.x + cos(m_angle) * m_radius, m_radius, -centre.y + sin(m_angle) * m_radius);
  180.     D3DXVECTOR3 Lookat = D3DXVECTOR3(centre.x, 0.0f,  -centre.y);
  181.  
  182.     D3DXMatrixIdentity(&matWorld);
  183.     D3DXMatrixLookAtLH(&matView, &Eye, &Lookat, &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  184.     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.3333f, 1.0f, 1000.0f );
  185.  
  186.     m_pDevice->SetTransform( D3DTS_WORLD,      &matWorld );
  187.     m_pDevice->SetTransform( D3DTS_VIEW,       &matView );
  188.     m_pDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  189.     
  190.     if(KEYDOWN('W'))
  191.     {
  192.         m_wireframe = !m_wireframe;
  193.         Sleep(300);
  194.     }
  195.     if(KEYDOWN(VK_SPACE))
  196.     {
  197.         m_terrain.GenerateRandomTerrain(3);
  198.     }
  199.     else if(KEYDOWN(VK_ADD) && m_radius < 200.0f)
  200.     {
  201.         m_radius += deltaTime * 30.0f;
  202.     }
  203.     else if(KEYDOWN(VK_SUBTRACT) && m_radius > 5.0f)
  204.     {
  205.         m_radius -= deltaTime * 30.0f;
  206.     }
  207.  
  208.     if(KEYDOWN(VK_ESCAPE))
  209.         Quit();
  210.  
  211.     return S_OK;
  212. }    
  213.  
  214. HRESULT APPLICATION::Render()
  215. {
  216.     // Clear the viewport
  217.     m_pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L );
  218.  
  219.     //FPS Calculation
  220.     m_fps++;
  221.     if(GetTickCount() - m_time > 1000)
  222.     {
  223.         m_lastFps = m_fps;
  224.         m_fps = 0;
  225.         m_time = GetTickCount();
  226.     }
  227.  
  228.     // Begin the scene 
  229.     if(SUCCEEDED(m_pDevice->BeginScene()))
  230.     {
  231.         if(m_wireframe)m_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);    
  232.         else m_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  233.  
  234.         m_terrain.Render();
  235.  
  236.         RECT r[] = {{10, 10, 0, 0}, {10, 30, 0, 0}, {10, 50, 0, 0}};
  237.         m_pFont->DrawText(NULL, "W: Toggle Wireframe", -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  238.         m_pFont->DrawText(NULL, "+/-: Zoom In/Out", -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  239.         m_pFont->DrawText(NULL, "Space: Randomize Terrain", -1, &r[2], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  240.  
  241.         //FPS
  242.         char number[50];
  243.         std::string text = "FPS: ";
  244.         text += _itoa(m_lastFps, number, 10);
  245.         RECT rc = {630, 10, 0, 0};
  246.         m_pFont->DrawText(NULL, text.c_str(), -1, &rc, DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  247.  
  248.         // End the scene.
  249.         m_pDevice->EndScene();
  250.         m_pDevice->Present(0, 0, 0, 0);
  251.     }
  252.  
  253.     return S_OK;
  254. }
  255.  
  256. HRESULT APPLICATION::Cleanup()
  257. {
  258.     try
  259.     {
  260.         m_terrain.Release();
  261.  
  262.         m_pFont->Release();
  263.         m_pDevice->Release();
  264.  
  265.         debug.Print("Application terminated");
  266.     }
  267.     catch(...){}
  268.  
  269.     return S_OK;
  270.  
  271. }
  272.  
  273. HRESULT APPLICATION::Quit()
  274. {
  275.     ::DestroyWindow(m_mainWindow);
  276.     ::PostQuitMessage(0);
  277.     return S_OK;
  278. }